local ComplexActExcel = require("excel.ComplexSrvActivity")
local BaseConfig = ComplexActExcel.base[1]
local ActivityConfig = ComplexActExcel.activity
local DateConfig = ComplexActExcel.date
local ActDefine = require("activity.Define")
local ActHandlerW = require("activity.HandlerW")
local InnerDataManagerFW = require("innerdata.InnerDataManagerFW")
local InnerDataDefine = require("innerdata.Define")
local ServerCommonFW = require("serverCommon.ServerCommonFW")
local DB = require("common.DB")
local LuaMongo = _G.lua_mongo
local Config = require("Config")
local Util = require("common.Util")
local PfLogic = require("tencentApi.PfLogic")
local Banshu = require("common.Banshu")

ComplexActDataList = ComplexActDataList or {}
ComplexActList = ComplexActList or {}
CallBackList = CallBackList or {}
GMDAY = GMDAY or 0

function onGetComplexDay()
    local nComplexTime = ServerCommonFW.getComplexSrvTime()
    local nServerComplexDateTime = os.date("*t", nComplexTime)
    local nStartDateTime = {}
    nStartDateTime.year = nServerComplexDateTime.year
    nStartDateTime.month = nServerComplexDateTime.month
    nStartDateTime.day = nServerComplexDateTime.day
    nStartDateTime.hour = 0
    nStartDateTime.min = 0
    nStartDateTime.sec = 0
    return os.time(nStartDateTime)
end

function onGetAllDateLen()
    return #DateConfig
end

function onGetCurDay(complexday, type)
    if complexday <= onGetAllDateLen() then
        return complexday
    end
    local nDiffDay = complexday - BaseConfig.day1
    local nMod = nDiffDay % nRoundLen
    if type == 1 then
        return math.floor(nDiffDay / nRoundLen), (nMod == 0 and 0 or (onGetNextRoundBegin() + nDiffDay % nRoundLen - 1))
    elseif type == 2 then
        return math.floor(nDiffDay / nRoundLen), (nMod == 0 and onGetAllDateLen() or (onGetNextRoundBegin() + nDiffDay % nRoundLen - 1))
    end
end


function ctlActList(complexday)
    local nComplexDay = complexday
    if nComplexDay > onGetAllDateLen() then
        return nil
    end
    local nTodayActList = {}

    local nTempDay = 1

    for i = 1, nComplexDay do
        if DateConfig[i] then
            for k, v in ipairs(DateConfig[i].openlist) do
                local nActConfigID = v[1]
                local nLastTime = v[3]
                if nActConfigID ~= ActDefine.OPERATEACT_TYPE_QPOINT  and not Banshu.isbstmAct(nActConfigID) or (nActConfigID == ActDefine.OPERATEACT_TYPE_QPOINT and not PfLogic.isAgentOther())then
                    if nTempDay + nLastTime > nComplexDay and not nTodayActList[nActConfigID] and not onCheckActIsRunning(nActConfigID) then
                        nTodayActList[nActConfigID] = v
                        nTodayActList[nActConfigID].startDateTime = onGetComplexDay() + ((nTempDay - 1) * 86400)
                        nTodayActList[nActConfigID].sort = k
                        local nEndDateTime = {}
                        local nTempEndDateTime = os.date("*t", nTodayActList[nActConfigID].startDateTime + ((nLastTime - 1) * 86400))
                        nEndDateTime.year = nTempEndDateTime.year
                        nEndDateTime.month = nTempEndDateTime.month
                        nEndDateTime.day = nTempEndDateTime.day
                        nEndDateTime.hour = 23
                        nEndDateTime.min = 59
                        nEndDateTime.sec = 59
                        nTodayActList[nActConfigID].endDateTime = os.time(nEndDateTime)
                    end
                end
            end
        end
        nTempDay = nTempDay + 1
    end
    return nTodayActList
end

function onActCheck()
    local nComplexDay = ServerCommonFW.getHadComplexSrvDay()
    if nComplexDay <= 0 then
        return
    end

    local nTimeStamp = os.time()
    if ComplexActList._today then
        for nActConfigID, v in pairs(ComplexActList._today) do
            if v._configList then
                local nStartTimeStamp = v._configList.startDateTime
                local nEndTimeStamp = v._configList.endDateTime
                local nLeftTime = ((nTimeStamp + GMDAY * 86400) >= nStartTimeStamp and (nTimeStamp + GMDAY * 86400) <= nEndTimeStamp) and nEndTimeStamp - (nTimeStamp + GMDAY * 86400) or 0
                if nLeftTime > 0 then
                    if not onProcessAct(nActConfigID, nLeftTime, ActDefine.ACT_STATE_RUNNING, v._configList) then

                    end
                end

                --检查进行中的活动
                if v._running then
                    local nEndTimeStamp = v._running.actArgs.endDateTime
                    if nEndTimeStamp <= (nTimeStamp + GMDAY * 86400) then      --活动到达结束时间
                        --onEndAct(v._running.actnum)
                        onProcessAct(nActConfigID, 0, ActDefine.ACT_STATE_ENDED, v._configList)
                    end
                end
            end
        end
    end
end

function onProcessAct(actConfigID, gap, actState, actArgs)
    local nActConfigData = ComplexActList._today[actConfigID]

    if not nActConfigData or not gap or not actState then
        return false
    end

    if actState == ActDefine.ACT_STATE_READY then
        onSend2LActUpdate(actConfigID, actState, actArgs)
    elseif actState == ActDefine.ACT_STATE_RUNNING then
        if not onCheckActIsRunning(actConfigID) then
            local nActVersionDate = tonumber(onGetActVersion(actConfigID))
            local nStartDate = tonumber(os.date("%Y%m%d", actArgs.startDateTime))
            local nEndDate = tonumber(os.date("%Y%m%d", actArgs.endDateTime))
            if nActVersionDate < nStartDate or nActVersionDate > nEndDate then
            --if onGetActVersion(actConfigID) ~= tonumber(os.date("%Y%m%d")) then
                ComplexActDataList[actConfigID] = {}
                ComplexActDataList[actConfigID]._data = {}
                onSetActVersion(actConfigID)
                onSetActDBData(actConfigID, ComplexActDataList[actConfigID]._data)
            end
            ComplexActDataList[actConfigID] = ComplexActDataList[actConfigID] or {_data = {}}
            nActConfigData._running = {actConfigID = actConfigID, actArgs = actArgs}
            onCallBack(actConfigID, actState, actArgs)
            onSend2LActUpdate(actConfigID, actState, actArgs)
            --ActHandlerW.onSendBroadcast(actConfigID, actState)
            ActHandlerW.onSend2ClientComplexSrvActUpdate(actConfigID, 2, actArgs)
            return true
        else
            if not nActConfigData._running or (nActConfigData._running and nActConfigData._running.actConfigID ~= actConfigID) then
                ActHandlerW.onSend2ClientComplexSrvActUpdate(actConfigID, 2, actArgs)
            end
        end
    elseif actState == ActDefine.ACT_STATE_ENDED then
        if not nActConfigData._endList[actConfigID] then
            nActConfigData._endList[actConfigID] = {}
        end
        onCallBack(actConfigID, actState, actArgs)
        nActConfigData._running = nil
        ActHandlerW.onSend2ClientComplexSrvActUpdate(actConfigID, 2, actArgs)
        onSend2LActUpdate(actConfigID, actState, actArgs)
        ComplexActDataList[actConfigID]._data = nil
        saveDB(actConfigID, ComplexActDataList[actConfigID])
        ComplexActList._today[actConfigID] = nil
        --ActHandlerW.onSendBroadcast(actConfigID, actState)
        return true
    end
    return false
end

function onSend2LActUpdate(actConfigID, status, actArgs)
    local nSend2Ldata = {
        type = 3,
        data = {
            status = status,
            actConfigID = actConfigID,
            actArgs = actArgs,
        }
    }
    InnerDataManagerFW.Send2LInnerData(nil, InnerDataDefine.INNERDATA_TYPE_ACT, nSend2Ldata)
end

function onGetTodayActList()
    return ComplexActList._today
end

function onGetActStatus(actConfigID, startDateTime, endDateTime)
    if ComplexActList._today[actConfigID] and ComplexActList._today[actConfigID]._running then
        return ActDefine.ACT_STATE_RUNNING
    else
        local nStartTimeStamp = startDateTime
        local nTimeStamp = os.time()
        if (nTimeStamp + (GMDAY * 86400))  < nStartTimeStamp then
            return ActDefine.ACT_STATE_READY
        else
            return ActDefine.ACT_STATE_ENDED
        end
    end
end

function onGetLeftTime(actConfigID, actArgs)
    local nActData = ComplexActList._today

    if not nActData then
        return 0
    end

    local nActConfigData = nActData[actConfigID]
    if nActConfigData then
        local nStatus = onGetActStatus(actConfigID, actArgs.startDateTime, actArgs.endDateTime)
        if nStatus == ActDefine.ACT_STATE_READY then
            return 0
        elseif nStatus == ActDefine.ACT_STATE_RUNNING then
            local nEndTimeStamp = actArgs.endDateTime
            local nTimeStamp = os.time()
            local nLeftTime = nEndTimeStamp - nTimeStamp - (GMDAY * 86400)
            return nLeftTime <= 0 and 0 or nLeftTime
        else
            return 0
        end
    end
end

function onGetCurActRuleID(actConfigID)
    if ComplexActList._today and ComplexActList._today[actConfigID] and ComplexActList._today[actConfigID]._running then
        return ComplexActList._today[actConfigID]._running.actArgs.ruleid
    end
end

function onCheckActIsRunning(actConfigID)
    if ComplexActList._today and ComplexActList._today[actConfigID] and ComplexActList._today[actConfigID]._running then
        return true
    end
end

function onDayChange(day1)
    GMDAY = day1
    onInitTodayAct()
    onActCheck()
end

function onRegisterCallBack(actConfigID, onBeginBefore, onRunning, onEnd, actArgs)
    CallBackList[actConfigID] = {[ActDefine.ACT_STATE_BEFORESTART] = onBeginBefore, [ActDefine.ACT_STATE_RUNNING] = onRunning, [ActDefine.ACT_STATE_ENDED] = onEnd, args = actArgs}
end

function onCallBack(actConfigID, status, actArgs)
    local nCallBackData = CallBackList[actConfigID]
    if nCallBackData and nCallBackData[status] then
        nCallBackData[status](actConfigID, actArgs, nCallBackData.args)
    end
end

function onSetActVersion(actConfigID)
    ComplexActDataList[actConfigID].version = tonumber(os.date("%Y%m%d"))
    ComplexActList._today[actConfigID]._configList.version = ComplexActDataList[actConfigID].version
end

function onGetActVersion(actConfigID)
    if not ComplexActDataList[actConfigID] or not ComplexActDataList[actConfigID].version then
        return 0
    end
    return ComplexActDataList[actConfigID].version
end

function onInitTodayAct(mustEnd)
    if Config.IS_MIDDLE then
        return
    end

    local nTimeStamp = os.time()

    --检查今天进行中的活动, 如果有要结束的这里要统一结束
    if ComplexActList._today then
        for nActConfigID, nActData in pairs(ComplexActList._today) do
            if nActData._running then
                --onEndAct(v._running.actnum)
                local nEndTimeStamp = nActData._running.actArgs.endDateTime
                if mustEnd or nEndTimeStamp <= (nTimeStamp + GMDAY * 86400) then      --活动到达结束时间
                    onProcessAct(nActConfigID, 0, ActDefine.ACT_STATE_ENDED, nActData)
                end
            end
        end
    end

    ComplexActList._today = ComplexActList._today or {}
    --如果服务器已开启时间小于等于0则不跑活动
    local nComplexDay = ServerCommonFW.getHadComplexSrvDay()
    if nComplexDay <= 0 then
        return
    end

    --开始初始化今日活动列表，初始化完后ComplexActList中将保存所有有效的活动
    local nTodayActList = ctlActList(nComplexDay)
    if nTodayActList then
        for nActConfigID, nActArgs in pairs(nTodayActList) do
            local nActRuleID = nActArgs[2]
            local nActConfigExcel = ActivityConfig[nActConfigID].actNum
            local nActRuleData = ComplexActExcel[nActConfigExcel][nActRuleID]
            if nActRuleData then
                if not ComplexActList._today[nActConfigID] or ComplexActList._today[nActConfigID]._running == nil then
                    if not ComplexActList._today[nActConfigID] then
                        ComplexActList._today[nActConfigID] = {
                            _beginbefore = nil,             --预告中的活动
                            _running = nil,                 --运行中的活动
                            _endList = {},
                        }
                    end

                    local nStartTimeStamp = nActArgs.startDateTime
                    local nEndTimeStamp = nActArgs.endDateTime
                    ComplexActList._today[nActConfigID]._configList = nil
                    ComplexActList._today[nActConfigID]._configList = {_configID = nActConfigID, version = onGetActVersion(nActConfigID), startDateTime = nStartTimeStamp, endDateTime = nEndTimeStamp, ruleid = nActRuleID, iconid = nActArgs[4], effectid = nActArgs[5], modletype = nActArgs[7], modleid = nActArgs[6], sort = nActArgs.sort}
                end
            end
        end
    end
end

function onGetActDesc(actConfigID, actRuleID)
    local nActConfigExcel = ActivityConfig[actConfigID].actNum
    if nActConfigExcel then
        local nActRuleData = ComplexActExcel[nActConfigExcel][actRuleID]
        if nActRuleData then
            return nActRuleData.desc or ""
        end
    end
end

function onSetActDBData(actConfigID, actData)
    ComplexActDataList[actConfigID] = ComplexActDataList[actConfigID] or {_data = {}} 
    ComplexActDataList[actConfigID]._data = actData
    ComplexActDataList[actConfigID].version = onGetActVersion(actConfigID)
    ComplexActDataList[actConfigID].actConfigID = actConfigID
    saveDB(actConfigID, ComplexActDataList[actConfigID])
end

function hasComplexSrvAct()
    local nHadComplexDay = ServerCommonFW.getHadComplexSrvDay()
    if nHadComplexDay > 0 and nHadComplexDay <= BaseConfig.day1 then
        return true
    end
end

function onGetActDBData(actConfigID)
    return ComplexActDataList[actConfigID] and ComplexActDataList[actConfigID]._data or nil
end

function saveDB(actConfigID, actData)
    LuaMongo.update(DB.db_complexact, {actConfigID = actConfigID}, actData, true)
end

initStatus = initStatus or false
function onInit(clear, day1, day2)
    if initStatus == false or clear then
        --if clear then
        --    for nType, v in pairs(ComplexActList) do
        --        for nActConfigID, nActData in pairs(v._configList) do
        --            for nActNum, nActArgs in pairs(nActData) do
        --                onProcessAct(nType, nActConfigID, nActNum, 0, ActDefine.ACT_STATE_ENDED, nActArgs)
        --            end
        --        end
        --        ComplexActList[nType] = nil
        --    end
        --end
        --initStatus = true
    end
    LuaMongo.find(DB.db_complexact)
    while true do
        local nReader = {}
        if not LuaMongo.next(nReader) then
            break
        end

        local actConfigID = nReader.actConfigID
        if actConfigID then
            ComplexActDataList[actConfigID] = {} 
            ComplexActDataList[actConfigID]._data = nReader._data
            ComplexActDataList[actConfigID].version = nReader.version or 0 
            ComplexActDataList[actConfigID].actConfigID = actConfigID
        end
    end
end

onInit()
